package com.atguigu.usercenterservice.controller;

import com.atguigu.commonutils.utils.JwtUtils;
import com.atguigu.servicebase.exceptionhandler.GuliException;
import com.atguigu.usercenterservice.client.HttpClientUtils;
import com.atguigu.usercenterservice.entity.UcenterMember;
import com.atguigu.usercenterservice.service.UcenterMemberService;
import com.atguigu.usercenterservice.utils.WechatPropertiesUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;

/**
 * @RestController 请求方法并返回数据  @Controller只请求方法  重定向不需要返回数据  只需要请求方法即可
 * 所以这里用@Controller
 */
@Controller
@Api(description = "微信开发者服务")
@RequestMapping("/api/ucenter/wx")
//@CrossOrigin
public class WxApiController {

    @Autowired
    private UcenterMemberService memberService;

    /**
     * 生成微信二维码
     * @return
     */
    @ApiOperation("生成微信二维码")
    @GetMapping("wxLogin")
    public String wxCode(){
        //拼接请求微信开发者平台的请求路径  网页应用scope作用域参数仅填写snsapi_login
//        String url = "https://open.weixin.qq.com/connect/qrconnect?appid=" + WechatPropertiesUtils.APP_ID +"&redirect_uri="
//                + WechatPropertiesUtils.REDIRECT_URL + "&response_type=code"
//                + "&scope=snsapi_login&state=STATE#wechat_redirect";
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        //业务服务器重定向地址
        String redirectUrl = WechatPropertiesUtils.REDIRECT_URL;
        try{
            //微信要求使用urlEncode对链接进行处理
            redirectUrl = URLEncoder.encode(redirectUrl,"UTF-8");//url编码
        }catch (UnsupportedEncodingException e){
            throw new GuliException(20001,e.getMessage());
        }
        // 防止csrf攻击（跨站请求伪造攻击）
        //String state = UUID.randomUUID().toString().replaceAll("-", "");//一般情况下会使用一个随机数
        String state = "atguigu";//为了让大家能够使用我搭建的外网的微信回调跳转服务器，这里填写你在ngrok的前置域名
        // 采用redis等进行缓存state 使用sessionId为key 30分钟后过期，可配置
        //键："wechar-open-state-" + httpServletRequest.getSession().getId()
        //值：satte
        //过期时间：30分钟

        //生成qrcodeUrl  想baseUrl的%s中冲入参数
        String qrcodeUrl = String.format(
                baseUrl,
                WechatPropertiesUtils.APP_ID,
                redirectUrl,
                state);
        //重定向到请求微信地址url里
        return "redirect:" + qrcodeUrl; //redirect重定向到生成二维码页面
    }


    /**
     * 扫描二维码回调
     * @param code 扫描二维码url后返回的参数
     * @param state 扫描二维码url后返回的参数
     * @return
     */
    @ApiOperation("扫描二维码回调")
    @GetMapping("callback")
    public String callBack(String code, String state){
        //从redis中将state获取出来，和当前传入的state作比较 TODO
        //如果一致则放行，如果不一致则抛出异常：非法访问

        //向微信认证服务器发送请求换取access_token
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
        "?appid=%s" +
        "&secret=%s" +
        "&code=%s" +
        "&grant_type=authorization_code";
        String accessTokenUrl = String.format(baseAccessTokenUrl,
                WechatPropertiesUtils.APP_ID,
                WechatPropertiesUtils.APP_SECRET,
                code);
        String result = null;
        try{
            //通过HttpClientUtils工具类发送get请求 得到返回的accessToken
            result = HttpClientUtils.get(accessTokenUrl);
        }catch (Exception e){
            throw new GuliException(20001,"获取access_token失败");
        }
        //解析json字符串获取accessToken和openId
        Gson gson = new Gson();
        HashMap map = gson.fromJson(result, HashMap.class);
        String accessToken = (String)map.get("access_token");
        String openid = (String)map.get("openid");
        //通过openId查询数据库是否已经注册
        QueryWrapper<UcenterMember> query = new QueryWrapper<>();
        query.eq("openid",openid);
        UcenterMember member = memberService.getOne(query);
        if (null == member){//新用户登陆
            //访问微信的资源服务器，获取用户信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
            "?access_token=%s" +
            "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
            String resultUserInfo = null;
            try{
                resultUserInfo = HttpClientUtils.get(userInfoUrl);
            }catch (Exception e){
                throw new GuliException(20001,"获取微信用户信息失败");
            }
            //解析json字符串
            HashMap<String, Object> mapUserInfo = gson.fromJson(resultUserInfo, HashMap.class);
            String nickname = (String)mapUserInfo.get("nickname");
            String headimgurl = (String)mapUserInfo.get("headimgurl");
            //向数据库中插入一条记录
            member = new UcenterMember();
            member.setNickname(nickname);
            member.setOpenid(openid);
            member.setAvatar(headimgurl);
            memberService.save(member);
        }
        //存入cookie
        //CookieUtils.setCookie(request, response, "guli_jwt_token", token);
        //整合JWT令牌 获取token
        String token = JwtUtils.getJwtToken(member.getId(),member.getNickname());
        //因为端口号不同存在蛞蝓问题，cookie不能跨域，所以这里使用url重写
        return "redirect:http://localhost:3000？token=" + token;
    }

}
